import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;

import '../models/api_response.dart';
import '../models/directory.dart' as dir;
import '../../core/exceptions/app_exception.dart';
import '../../core/constants/api_constants.dart';

/// 目录API服务
class DirectoriesApi {
  final http.Client _client;
  String? _authToken;

  DirectoriesApi({http.Client? client}) : _client = client ?? http.Client();

  /// 设置认证令牌
  void setAuthToken(String token) {
    _authToken = token;
  }

  /// 检查认证令牌
  void _checkAuthToken() {
    if (_authToken == null) {
      throw UnauthenticatedException('未认证，请先登录');
    }
  }

  /// 获取认证头
  Map<String, String> get _headers {
    return {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer $_authToken',
    };
  }

  /// 发送GET请求
  Future<Map<String, dynamic>> _sendGetRequest(String url) async {
    try {
      _checkAuthToken();
      debugPrint('GET请求开始: $url');
      final uri = Uri.parse(url);

      // 发送请求
      final response = await _client
          .get(uri, headers: _headers)
          .timeout(
            Duration(seconds: ApiConstants.timeout),
            onTimeout: () => throw NetworkException('请求超时，请检查网络连接'),
          );

      debugPrint('GET请求状态码: ${response.statusCode}');
      final responseBody = utf8.decode(response.bodyBytes);
      debugPrint('GET请求返回内容: $responseBody');

      // 处理服务器错误
      if (response.statusCode >= 500) {
        throw NetworkException('服务器错误(${response.statusCode}): $responseBody');
      }

      // 处理认证错误
      if (response.statusCode == 401) {
        throw UnauthenticatedException('认证失败，请重新登录');
      }

      // 解析响应JSON
      Map<String, dynamic>? responseData;
      try {
        responseData = jsonDecode(responseBody) as Map<String, dynamic>?;
      } catch (e) {
        throw FormatException('返回数据格式错误: $responseBody');
      }

      if (responseData == null) {
        throw ApiException('服务器返回空数据');
      }

      return responseData;
    } catch (e) {
      debugPrint('GET请求异常: $e');
      if (e is AppException) rethrow;
      throw NetworkException('网络请求失败: ${e.toString()}');
    }
  }

  /// 发送POST请求
  Future<Map<String, dynamic>> _sendPostRequest(
    String url, {
    Map<String, dynamic>? body,
  }) async {
    try {
      _checkAuthToken();
      debugPrint('POST请求开始: $url, 请求体: $body');
      final uri = Uri.parse(url);

      // 转换为JSON字符串
      final String jsonBody = body != null ? jsonEncode(body) : '{}';

      // 发送请求
      final response = await _client
          .post(uri, headers: _headers, body: jsonBody)
          .timeout(
            Duration(seconds: ApiConstants.timeout),
            onTimeout: () => throw NetworkException('请求超时，请检查网络连接'),
          );

      debugPrint('POST请求状态码: ${response.statusCode}');
      final responseBody = utf8.decode(response.bodyBytes);
      debugPrint('POST请求返回内容: $responseBody');

      // 处理服务器错误
      if (response.statusCode >= 500) {
        throw NetworkException('服务器错误(${response.statusCode}): $responseBody');
      }

      // 处理认证错误
      if (response.statusCode == 401) {
        throw UnauthenticatedException('认证失败，请重新登录');
      }

      // 解析响应JSON
      Map<String, dynamic>? responseData;
      try {
        responseData = jsonDecode(responseBody) as Map<String, dynamic>?;
      } catch (e) {
        throw FormatException('返回数据格式错误: $responseBody');
      }

      if (responseData == null) {
        throw ApiException('服务器返回空数据');
      }

      return responseData;
    } catch (e) {
      debugPrint('POST请求异常: $e');
      if (e is AppException) rethrow;
      throw NetworkException('网络请求失败: ${e.toString()}');
    }
  }

  /// 发送PUT请求
  Future<Map<String, dynamic>> _sendPutRequest(
    String url, {
    Map<String, dynamic>? body,
  }) async {
    try {
      _checkAuthToken();
      debugPrint('PUT请求开始: $url, 请求体: $body');
      final uri = Uri.parse(url);

      // 转换为JSON字符串
      final String jsonBody = body != null ? jsonEncode(body) : '{}';

      // 发送请求
      final response = await _client
          .put(uri, headers: _headers, body: jsonBody)
          .timeout(
            Duration(seconds: ApiConstants.timeout),
            onTimeout: () => throw NetworkException('请求超时，请检查网络连接'),
          );

      debugPrint('PUT请求状态码: ${response.statusCode}');
      final responseBody = utf8.decode(response.bodyBytes);
      debugPrint('PUT请求返回内容: $responseBody');

      // 处理服务器错误
      if (response.statusCode >= 500) {
        throw NetworkException('服务器错误(${response.statusCode}): $responseBody');
      }

      // 处理认证错误
      if (response.statusCode == 401) {
        throw UnauthenticatedException('认证失败，请重新登录');
      }

      // 解析响应JSON
      Map<String, dynamic>? responseData;
      try {
        responseData = jsonDecode(responseBody) as Map<String, dynamic>?;
      } catch (e) {
        throw FormatException('返回数据格式错误: $responseBody');
      }

      if (responseData == null) {
        throw ApiException('服务器返回空数据');
      }

      return responseData;
    } catch (e) {
      debugPrint('PUT请求异常: $e');
      if (e is AppException) rethrow;
      throw NetworkException('网络请求失败: ${e.toString()}');
    }
  }

  /// 发送DELETE请求
  Future<Map<String, dynamic>> _sendDeleteRequest(String url) async {
    try {
      _checkAuthToken();
      debugPrint('DELETE请求开始: $url');
      final uri = Uri.parse(url);

      // 发送请求
      final response = await _client
          .delete(uri, headers: _headers)
          .timeout(
            Duration(seconds: ApiConstants.timeout),
            onTimeout: () => throw NetworkException('请求超时，请检查网络连接'),
          );

      debugPrint('DELETE请求状态码: ${response.statusCode}');
      final responseBody = utf8.decode(response.bodyBytes);
      debugPrint('DELETE请求返回内容: $responseBody');

      // 处理服务器错误
      if (response.statusCode >= 500) {
        throw NetworkException('服务器错误(${response.statusCode}): $responseBody');
      }

      // 处理认证错误
      if (response.statusCode == 401) {
        throw UnauthenticatedException('认证失败，请重新登录');
      }

      // 解析响应JSON
      Map<String, dynamic>? responseData;
      try {
        responseData = jsonDecode(responseBody) as Map<String, dynamic>?;
      } catch (e) {
        throw FormatException('返回数据格式错误: $responseBody');
      }

      if (responseData == null) {
        throw ApiException('服务器返回空数据');
      }

      return responseData;
    } catch (e) {
      debugPrint('DELETE请求异常: $e');
      if (e is AppException) rethrow;
      throw NetworkException('网络请求失败: ${e.toString()}');
    }
  }

  /// 获取目录列表
  Future<ApiResponse<List<dir.Directory>>> getDirectories({
    int? parentId,
  }) async {
    String url = '${ApiConstants.baseUrl}${DirectoriesApiConstants.list}';

    // 如果有父目录ID，添加查询参数
    if (parentId != null) {
      url += '?parent_id=$parentId';
    }

    final responseData = await _sendGetRequest(url);

    return ApiResponse<List<dir.Directory>>.fromJson(responseData, (data) {
      if (data == null || data['items'] == null) return [];

      final items = data['items'] as List;
      return items
          .map((item) => dir.Directory.fromJson(item as Map<String, dynamic>))
          .toList();
    });
  }

  /// 获取目录树
  Future<ApiResponse<List<dir.Directory>>> getDirectoryTree() async {
    final String url = '${ApiConstants.baseUrl}${DirectoriesApiConstants.tree}';
    final responseData = await _sendGetRequest(url);

    return ApiResponse<List<dir.Directory>>.fromJson(responseData, (data) {
      if (data == null || data['tree'] == null) return [];

      final tree = data['tree'] as List;
      return tree
          .map((item) => dir.Directory.fromJson(item as Map<String, dynamic>))
          .toList();
    });
  }

  /// 获取单个目录详情
  Future<ApiResponse<dir.Directory>> getDirectory(int directoryId) async {
    final String url =
        '${ApiConstants.baseUrl}${DirectoriesApiConstants.get(directoryId)}';
    final responseData = await _sendGetRequest(url);

    return ApiResponse<dir.Directory>.fromJson(responseData, (data) {
      if (data == null) return null;
      return dir.Directory.fromJson(data as Map<String, dynamic>);
    });
  }

  /// 创建目录
  Future<ApiResponse<dir.Directory>> createDirectory({
    required String name,
    int parentId = 0, // 默认为根目录
  }) async {
    final String url = '${ApiConstants.baseUrl}${DirectoriesApiConstants.list}';
    final responseData = await _sendPostRequest(
      url,
      body: {'name': name, 'parent_id': parentId},
    );

    return ApiResponse<dir.Directory>.fromJson(responseData, (data) {
      if (data == null) return null;
      return dir.Directory.fromJson(data as Map<String, dynamic>);
    });
  }

  /// 更新目录
  Future<ApiResponse<dir.Directory>> updateDirectory({
    required int directoryId,
    String? name,
    int? parentId,
  }) async {
    final String url =
        '${ApiConstants.baseUrl}${DirectoriesApiConstants.update(directoryId)}';

    // 构建请求体，只包含需要更新的字段
    final Map<String, dynamic> body = {};
    if (name != null) body['name'] = name;
    if (parentId != null) body['parent_id'] = parentId;

    final responseData = await _sendPutRequest(url, body: body);

    return ApiResponse<dir.Directory>.fromJson(responseData, (data) {
      if (data == null) return null;
      return dir.Directory.fromJson(data as Map<String, dynamic>);
    });
  }

  /// 删除单个目录
  @Deprecated('使用batchDeleteItems方法替代')
  Future<ApiResponse<void>> deleteDirectory(int directoryId) async {
    final String url =
        '${ApiConstants.baseUrl}${DirectoriesApiConstants.delete(directoryId)}';
    final responseData = await _sendDeleteRequest(url);

    return ApiResponse<void>.fromJson(responseData, (_) => null);
  }

  /// 批量删除目录和文件
  Future<ApiResponse<BatchDeleteResult>> batchDeleteItems({
    List<int>? directoryIds,
    List<int>? fileIds,
    bool permanent = false,
    bool recursive = true,
  }) async {
    final String url =
        '${ApiConstants.baseUrl}${DirectoriesApiConstants.batchDelete}';
    final Map<String, dynamic> body = {
      'permanent': permanent,
      'recursive': recursive,
    };

    if (directoryIds != null && directoryIds.isNotEmpty) {
      body['directory_ids'] = directoryIds;
    }

    if (fileIds != null && fileIds.isNotEmpty) {
      body['file_ids'] = fileIds;
    }

    final responseData = await _sendPostRequest(url, body: body);

    return ApiResponse<BatchDeleteResult>.fromJson(responseData, (data) {
      if (data == null) return null;
      return BatchDeleteResult.fromJson(data as Map<String, dynamic>);
    });
  }

  /// 移动目录和文件到指定目录
  Future<ApiResponse<MoveItemsResult>> moveItems({
    List<int>? directoryIds,
    List<int>? fileIds,
    required int targetDirectoryId,
  }) async {
    final String url =
        '${ApiConstants.baseUrl}${DirectoriesApiConstants.moveItems}';
    final Map<String, dynamic> body = {
      'target_directory_id': targetDirectoryId,
    };

    if (directoryIds != null && directoryIds.isNotEmpty) {
      body['directory_ids'] = directoryIds;
    }

    if (fileIds != null && fileIds.isNotEmpty) {
      body['file_ids'] = fileIds;
    }

    final responseData = await _sendPostRequest(url, body: body);

    return ApiResponse<MoveItemsResult>.fromJson(responseData, (data) {
      if (data == null) return null;
      return MoveItemsResult.fromJson(data as Map<String, dynamic>);
    });
  }

  /// 获取目录下的文件
  Future<ApiResponse<List<FileItem>>> getDirectoryFiles(int directoryId) async {
    final String url =
        '${ApiConstants.baseUrl}${DirectoriesApiConstants.files(directoryId)}';
    final responseData = await _sendGetRequest(url);

    return ApiResponse<List<FileItem>>.fromJson(responseData, (data) {
      if (data == null || data['items'] == null) return [];

      final items = data['items'] as List;
      return items
          .map((item) => FileItem.fromJson(item as Map<String, dynamic>))
          .toList();
    });
  }

  /// 释放资源
  void dispose() {
    _client.close();
  }
}

/// 批量删除结果
class BatchDeleteResult {
  final DirectoryDeleteResult directories;
  final FileDeleteResult files;
  final int totalSuccessCount;
  final int totalFailedCount;
  final bool isPermanent;

  BatchDeleteResult({
    required this.directories,
    required this.files,
    required this.totalSuccessCount,
    required this.totalFailedCount,
    required this.isPermanent,
  });

  factory BatchDeleteResult.fromJson(Map<String, dynamic> json) {
    return BatchDeleteResult(
      directories: DirectoryDeleteResult.fromJson(json['directories']),
      files: FileDeleteResult.fromJson(json['files']),
      totalSuccessCount: json['total_success_count'],
      totalFailedCount: json['total_failed_count'],
      isPermanent: json['is_permanent'],
    );
  }
}

/// 目录删除结果
class DirectoryDeleteResult {
  final int successCount;
  final int failedCount;
  final List<Map<String, dynamic>> failedDirectories;
  final int? affectedFilesCount;

  DirectoryDeleteResult({
    required this.successCount,
    required this.failedCount,
    required this.failedDirectories,
    this.affectedFilesCount,
  });

  factory DirectoryDeleteResult.fromJson(Map<String, dynamic> json) {
    List<Map<String, dynamic>> failedDirs = [];
    if (json['failed_directories'] != null) {
      final failedList = json['failed_directories'] as List;
      failedDirs =
          failedList.map((item) => item as Map<String, dynamic>).toList();
    }

    return DirectoryDeleteResult(
      successCount: json['success_count'],
      failedCount: json['failed_count'],
      failedDirectories: failedDirs,
      affectedFilesCount: json['affected_files_count'],
    );
  }
}

/// 文件删除结果
class FileDeleteResult {
  final int successCount;
  final int failedCount;
  final List<Map<String, dynamic>> failedFiles;

  FileDeleteResult({
    required this.successCount,
    required this.failedCount,
    required this.failedFiles,
  });

  factory FileDeleteResult.fromJson(Map<String, dynamic> json) {
    List<Map<String, dynamic>> failedFilesList = [];
    if (json['failed_files'] != null) {
      final failedList = json['failed_files'] as List;
      failedFilesList =
          failedList.map((item) => item as Map<String, dynamic>).toList();
    }

    return FileDeleteResult(
      successCount: json['success_count'],
      failedCount: json['failed_count'],
      failedFiles: failedFilesList,
    );
  }
}

/// 移动项目结果
class MoveItemsResult {
  final FileOperationResult files;
  final DirectoryOperationResult directories;
  final int totalSuccessCount;
  final int totalFailedCount;

  MoveItemsResult({
    required this.files,
    required this.directories,
    required this.totalSuccessCount,
    required this.totalFailedCount,
  });

  factory MoveItemsResult.fromJson(Map<String, dynamic> json) {
    return MoveItemsResult(
      files: FileOperationResult.fromJson(json['files']),
      directories: DirectoryOperationResult.fromJson(json['directories']),
      totalSuccessCount: json['total_success_count'],
      totalFailedCount: json['total_failed_count'],
    );
  }
}

/// 文件操作结果
class FileOperationResult {
  final int successCount;
  final int failedCount;
  final List<Map<String, dynamic>> failedFiles;

  FileOperationResult({
    required this.successCount,
    required this.failedCount,
    required this.failedFiles,
  });

  factory FileOperationResult.fromJson(Map<String, dynamic> json) {
    List<Map<String, dynamic>> failedFilesList = [];
    if (json['failed_files'] != null) {
      final failedList = json['failed_files'] as List;
      failedFilesList =
          failedList.map((item) => item as Map<String, dynamic>).toList();
    }

    return FileOperationResult(
      successCount: json['success_count'],
      failedCount: json['failed_count'],
      failedFiles: failedFilesList,
    );
  }
}

/// 目录操作结果
class DirectoryOperationResult {
  final int successCount;
  final int failedCount;
  final List<Map<String, dynamic>> failedDirectories;

  DirectoryOperationResult({
    required this.successCount,
    required this.failedCount,
    required this.failedDirectories,
  });

  factory DirectoryOperationResult.fromJson(Map<String, dynamic> json) {
    List<Map<String, dynamic>> failedDirs = [];
    if (json['failed_directories'] != null) {
      final failedList = json['failed_directories'] as List;
      failedDirs =
          failedList.map((item) => item as Map<String, dynamic>).toList();
    }

    return DirectoryOperationResult(
      successCount: json['success_count'],
      failedCount: json['failed_count'],
      failedDirectories: failedDirs,
    );
  }
}

/// 文件项
class FileItem {
  final int id;
  final int userId;
  final String fileName;
  final String filePath;
  final String fileType;
  final int fileSize;
  final String hash;
  final DateTime uploadTime;
  final DateTime createTime;
  final String extension;
  final String mimeType;
  final String? remark;
  final bool isDeleted;
  final int directoryId;

  FileItem({
    required this.id,
    required this.userId,
    required this.fileName,
    required this.filePath,
    required this.fileType,
    required this.fileSize,
    required this.hash,
    required this.uploadTime,
    required this.createTime,
    required this.extension,
    required this.mimeType,
    this.remark,
    required this.isDeleted,
    required this.directoryId,
  });

  factory FileItem.fromJson(Map<String, dynamic> json) {
    return FileItem(
      id: json['id'],
      userId: json['user_id'],
      fileName: json['file_name'],
      filePath: json['file_path'],
      fileType: json['file_type'],
      fileSize: json['file_size'],
      hash: json['hash'],
      uploadTime: DateTime.parse(json['upload_time']),
      createTime: DateTime.parse(json['create_time']),
      extension: json['extension'],
      mimeType: json['mime_type'],
      remark: json['remark'],
      isDeleted: json['is_deleted'] ?? false,
      directoryId: json['directory_id'],
    );
  }
}
